package com.navinfo.platform.trip.common.arithmetic;

import com.navinfo.platform.trip.common.arithmetic.data.CommonData;
import com.navinfo.platform.trip.common.arithmetic.data.OuterStatisticData;
import com.navinfo.platform.trip.common.arithmetic.var.VarSharpTurning;
import com.navinfo.platform.trip.common.arithmetic.manager.AbstractArithmetic;
import com.navinfo.platform.trip.common.config.ConfigMap;

/**
 * 东风急转弯算法<br/>
 * 输出：统计<br/>
 * @author web
 */
public class SharpTurning_DF extends AbstractArithmetic<VarSharpTurning> {
    /**
     * gps方向变化合法阈值，单位：度，默认60
     */
    private Integer validDirection = ConfigMap.getInteger("DF_Valid_Direction_Threshold");
    /**
     * 方向差阀值，单位：度，默认45
     */
    private Integer directionThreshold = ConfigMap.getInteger("DF_ST_Direction_Threshold");
    /**
     * 速度阀值，单位：km/h，默认30
     */
    private Integer speedThreshold = ConfigMap.getInteger("DF_ST_Speed_Threshold");
    /**
     * 时间阈值，单位：ms，默认30000
     */
    private Integer timeThreshold = ConfigMap.getInteger("DF_ST_Time_Threshold");

    /**
     * 方向变化是否合理
     * @param curDirection
     * @param preDirection
     * @return
     */
    private boolean directionIsValid(int curDirection, int preDirection) {
        return Math.abs(curDirection - preDirection) <= validDirection ||
                Math.abs(curDirection - preDirection) >= (360 - validDirection);
    }

    /**
     * 急转弯判断
     * 连续4个点的gps方向变化超过45度(或者低于360-45，因为gps方向359度之后就是0度)，车速＞30公里km/h
     * @param speedKmh
     * @param changedDirection
     * @return
     */
    private boolean isSharpTurn(int speedKmh, int changedDirection) {
        changedDirection = Math.abs(changedDirection);
        if(changedDirection > 180 ){
            changedDirection = 360 - changedDirection;
        }
        return changedDirection>= directionThreshold  && speedKmh >= speedThreshold;
    }

    @Override
    public void calculate() {
        logger.debug("进入东风急转弯算法...");
        VarSharpTurning obj = getObj();
        CommonData commonData = getCommonData();

        int[] directionArr = obj.getDirectionArr();
        int curDirection = commonData.getGpsDirection();

        //处理第一个点
        if(directionArr[0] == -1){
            directionArr[0] = curDirection;
            return;
        }

        //累积四个点的数组是否初始化完毕
        boolean isInit = true;

        //初始化数组
        for (int i=1; i<directionArr.length; i++) {
            //累积的4个点还没凑齐
            if (directionArr[i] == -1) {
                isInit = false;

                //当前gps方向和上一点的gps方向差合法，则初始化数组
                if (directionIsValid(curDirection, directionArr[i-1])) {
                    directionArr[i] = curDirection;

                    //初始化完数组最后1位
                    if (i == directionArr.length-1) {
                        logger.debug("东风急转弯算法，数组初始化完毕....");
                        isInit = true;
                    }
                }

                //不合法则重新初始化
                else {
                    obj.clearDirectionArr(curDirection);
                }

                //还有没初始化的点，退出循环
                break;
            }
        }

        //如果数组已初始化完毕，则进行急转弯计算
        if (isInit) {
            logger.debug("进行急转弯计算....");
            //取出最后一个方向
            int fourth = directionArr[3];

            //校验当前点和上一点的gps方向变化是否合法
            if (directionIsValid(curDirection, fourth)) {
                long gpsTime = commonData.getGpsTime();
                int speedKmh = commonData.getSpeedKmh();

                //数组左移，把当前方向放到数组最后1位
                for (int i = 0; i < directionArr.length - 1; i++) {
                    directionArr[i] = directionArr[i + 1];
                }
                directionArr[3] = curDirection;

                //可以过滤掉s弯和方向左右偏移
                int changedDirection = Math.abs(directionArr[3] - directionArr[0]);

                //3个点的gps方向改变超过45度或者小于315度(359度之后为0度)，则为急转弯
                boolean isSharpTurn = isSharpTurn(speedKmh, changedDirection);
                if (isSharpTurn) {
                    //距离上一个急转弯时间超过30s，则设为急转弯，否则为连续急转弯
                    if ((gpsTime - obj.getPreSharpTurningTime()) >= timeThreshold) {
                        obj.setNumber(obj.getNumber()+1);
                        obj.setPreSharpTurningTime(gpsTime);
                    } else {
                        obj.setPreSharpTurningTime(gpsTime);
                    }
                }
                logger.debug("开始东风急转弯计算 -- 终端号:{}, 时间:{}, 当前速度:{}, 连续4点方向{},{},{},{},方向变化:{}, 是否急转弯:{}, 距离上次急转弯时间{}",
                        terminalId,gpsTime, speedKmh,directionArr[0],directionArr[1], directionArr[2],directionArr[3],changedDirection,isSharpTurn,gpsTime - obj.getPreSharpTurningTime());
            }
            else {
                //当前gps方向和上一个gps方向差过大，说明数据出现了问题，则清空缓存，重新累积
                obj.clearDirectionArr(curDirection);
            }
        }

        logger.debug("离开东风急转弯算法...");
    }

    @Override
    public void collect(OuterStatisticData statisticDataOut) {
        statisticDataOut.setSharpTurningNumber_DF(getObj().getNumber());
    }
}
